#include <func.h>

//生产者，消费者
int main()
{
    int shmid;
    //第一次是创建，如果是另外一个进程，就是通过shmget获取shmid
    shmid=shmget(1000,4096,0600|IPC_CREAT);
    ERROR_CHECK(shmid,-1,"shmget");
    //连接到本进程的进程地址空间内
    int *p=(int*)shmat(shmid,NULL,0);

    //获取key为1000的信号量集合
    int semArrid=semget(1000,1,IPC_CREAT|0600);
    ERROR_CHECK(semArrid,-1,"semget");
    //信号量要初始化为1
    int ret=semctl(semArrid,0,SETVAL,1);
    ERROR_CHECK(semArrid,-1,"semctl");
    struct sembuf P;
    P.sem_num = 0;//信号量值在集合中的下标
    P.sem_op = -1;//信号量值修改
    P.sem_flg = SEM_UNDO;//如果P操作被终止，会自动恢复
    struct sembuf V;
    V.sem_num = 0;//信号量值在集合中的下标
    V.sem_op = 1;//信号量值修改
    V.sem_flg = SEM_UNDO;//如果V操作被终止，会自动恢复

    p[0] = 0;//仓库里边产品数目
    p[1] = 10;//仓库位置数目
    if(!fork())
    {
        //子进程是消费者
        while(1){
            sleep(2);
            printf("I am consumer, before consume, product = %d, space =%d\n",p[0],p[1]);
            semop(semArrid,&P,1);
            if(p[0] > 0){
                --p[0];
                printf("Buy a product\n");
                ++p[1];
            }
            semop(semArrid,&V,1);
            printf("I am consumer, after consume, product = %d, space =%d\n",p[0],p[1]);
        }
    }else
    {
        //父进程是生产者
        //父进程是生产者
        while(1){
            sleep(1);
            printf("I am producer, before produce, product = %d, space =%d\n",p[0],p[1]);
            semop(semArrid,&P,1);//入库时，子进程没办法同时出库
            if(p[1] > 0){
                --p[1];
                printf("Produce a product\n");
                ++p[0];
            }
            semop(semArrid,&V,1);
            printf("I am producer, after produce, product = %d, space = %d\n",p[0],p[1]);
        }
    }
}